package pandora.apps.d3mob.view;

import java.util.ArrayList;

import javax.microedition.khronos.opengles.GL10;
import com.e3roid.E3Scene;
import com.e3roid.drawable.Shape;
import com.e3roid.drawable.Sprite;
import com.e3roid.drawable.controls.StickController;
import com.e3roid.drawable.modifier.ProgressAware;
import com.e3roid.drawable.sprite.AnimatedSprite;
import com.e3roid.drawable.tmx.TMXLayer;

public class KingMoveModifier extends ProgressAware {
	
	private int lastX, lastY;
	private ArrayList<TMXLayer> mapLayers;
	private AnimatedSprite king;
	private E3Scene scene;
	private TMXLayer collisionLayer;
	private int dir;
	private static final int SCROLL_ZONE_WIDTH_X = 20,
							SCROLL_ZONE_WIDTH_Y = 20;
	
	public KingMoveModifier(int currentX, int minValueX, int maxValueX,
			int currentY, int minValueY, int maxValueY) {
		super(currentX, minValueX, maxValueX, currentY, minValueY, maxValueY);
		int x = maxValueX - currentX;
		int y = maxValueY - currentY;
		int dir;
		if (Math.abs(x)>=Math.abs(y)) {
			if (x >= 0) {
				dir = StickController.RIGHT;
			} else {
				dir = StickController.LEFT;
			}
		} else {
			if (y >= 0) {
				dir = StickController.DOWN;
			} else {
				dir = StickController.UP;
			}
		}
		this.dir = dir;
	}
	
	public Sprite getKing() {
		return king;
	}

	public void setKing(AnimatedSprite king) {
		this.king = king;
		this.lastX = king.getRealX();
		this.lastY = king.getRealY();
	}
	
	public void setMapLayers(ArrayList<TMXLayer> mapLayers) {
		this.mapLayers = mapLayers;
	}
	
	public E3Scene getScene() {
		return scene;
	}

	public void setScene(E3Scene scene) {
		this.scene = scene;
	}

	public TMXLayer getCollisionLayer() {
		return collisionLayer;
	}

	public void setCollisionLayer(TMXLayer collisionLayer) {
		this.collisionLayer = collisionLayer;
	}
	
	public int getDir() {
		return dir;
	}

	@Override
	public void onBeforeUpdate(Shape shape, GL10 gl10) {

	}
	
	@Override
	public void updateProgressValueA(float value, float percent) {
		int valuei = (int)value;
		int xstep = valuei - lastX;
		if (!collidesWithTile(king, xstep, 0) &&
				isInTheScene(king, xstep, 0)) {
			if (isInScrollZone(king,xstep,0)) {
				for (TMXLayer layer : mapLayers) {
					layer.scroll(layer.getX() + (int) xstep, layer.getY());
				}
			}
			king.moveRelative((int)xstep,0);
			this.lastX = valuei;
			super.updateProgressValueA(value, percent);
		} else {
			super.finish(king);
		}
	}
	
	@Override
	public void updateProgressValueB(float value, float percent) {
		int valuei = (int)value;
		int ystep = valuei - lastY;
		if (!collidesWithTile(king, 0, ystep) &&
				isInTheScene(king, 0, ystep)) {
			if (isInScrollZone(king,0,ystep)) {
				for (TMXLayer layer : mapLayers) {
					layer.scroll(layer.getX(), layer.getY() + (int)ystep);
				}
			}
			king.moveRelative(0, (int)ystep);
			this.lastY = valuei;
			super.updateProgressValueB(value, percent);
		} else {
			super.finish(king);
		}
	}
	
	
	@Override
	public void onAfterUpdate(Shape shape, GL10 gl10) {		
		// TODO Auto-generated method stub
	}
	
	public boolean isInTheScene(Shape sprite, int xstep, int ystep) {
		int x = sprite.getRealX() + xstep;
		int y = sprite.getRealY() + ystep;
		return x > 0 && y > 0 && x < scene.getWidth()  - sprite.getWidth() &&
				y < scene.getHeight() - sprite.getHeight();
	}
	
	public boolean collidesWithTile(Shape sprite, int xstep, int ystep) {
		if (collisionLayer == null) return false;
		return collisionLayer.getTileFromRect(sprite.getCollisionRect(), xstep, ystep).size() != 0;
	}
	
	public boolean isInScrollZone(Shape sprite, int xstep, int ystep) {
		int x = sprite.getRealX() + sprite.getWidth()/2 + xstep;
		int y = sprite.getRealY() + sprite.getHeight()/2 + ystep;
		int sceneW = scene.getWidth();
		int sceneH = scene.getHeight();
		
		return (dir == StickController.RIGHT && x >= sceneW/2 + SCROLL_ZONE_WIDTH_X) || (dir == StickController.LEFT && x <= sceneW/2 - SCROLL_ZONE_WIDTH_X) ||
				(dir == StickController.DOWN && y >= sceneH/2 + SCROLL_ZONE_WIDTH_Y) || (dir == StickController.UP && y <= sceneH/2 - SCROLL_ZONE_WIDTH_Y);
	}
}
